﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using RPGProject.Data_Structures;
using RPGProject.GameWorld.GameObjects;

namespace RPGProject.GameWorld
{
    sealed partial class World
    {
        /// <summary>
        /// Reloads the world from the filename
        /// </summary>
        /// <param name="fileName"></param>
        public void Reload(String fileName)
        {
            // Clear the scripts and spawn points
            this.scripts.Clear();
            this.spawnPoints.Clear();
            Vector<String> mapArray = new Vector<string>();
            StreamReader sr = new StreamReader(fileName);
            // Read in the height and check if it matches
            int width = 0;
            int height = 0;
            width = Int32.Parse(sr.ReadLine());
            height = Int32.Parse(sr.ReadLine());
            if (width != (int)this["width"] || height != (int)this["height"])
            {
                throw new Exception("New map doesn't match old map size.");
            }
            // Read in the map
            for (int i = 0; i < height; i++)
            {
                mapArray.Add(sr.ReadLine());
            }
            // Read in the scripts
            while (!sr.EndOfStream)
            {
                this.AddScript(sr.ReadLine());
            }

            String[] map = mapArray.ToArray();

            int enemySpawnpoints = 0;
            // begin world init y
            for (int i = 0; i < map.Length; i++)
            {
                // begin world init x
                for (int j = 0; j < map[i].Length; j++)
                {
                    // begin char type switch
                    switch (map[i][j])
                    {
                            // its ocean
                        case 'B':
                            this.PutGameObject(new NullGameObject(j, i));
                            this.PutMapTile(new MapTile(j, i, ConsoleColor.DarkBlue));
                            break;
                            // its the player spawnpoint
                        case 'P':
                            this.PutGameObject(new NullGameObject(j, i));
                            this.PutSpawnPoint(new SpawnPoint(j, i, "player"));
                            this.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                            // its an enemy spawnpoint
                        case 'E':
                            this.PutGameObject(new NullGameObject(j, i));
                            this.PutSpawnPoint(new SpawnPoint(j, i, "enemy" + enemySpawnpoints++));
                            this.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                            // Its empty
                        case ' ':
                            this.PutGameObject(new NullGameObject(j, i));
                            this.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                            // Its a wall of some sort
                        case '+':
                        case '|':
                        case '-':
                        default:
                            this.PutGameObject(new Wall(j, i, map[i][j], ConsoleColor.Gray));
                            MapTile put = new MapTile(j, i);
                            put.background = ConsoleColor.Gray;
                            this.PutMapTile(put);
                            break;

                    }
                    // end char type switch
                }
                // end world init x
            }
            // end world init y
        }
        /// <summary>
        /// Load the world initially to toWorld from the filename and with a statHeight and bufferHeight specified.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="toWorld"></param>
        /// <param name="statHeight"></param>
        /// <param name="bufferHeight"></param>
        public static void Load(String fileName, out World toWorld, int statHeight, int bufferHeight)
        {
            // loads map
            Vector<String> mapArray = new Vector<string>();
            StreamReader sr = new StreamReader(fileName);
            // Reads the width x height and creates a new world from it
            int width = 0;
            int height = 0;
            width = Int32.Parse(sr.ReadLine());
            height = Int32.Parse(sr.ReadLine());
            toWorld = new World(width, height, statHeight, bufferHeight);
            // Reads in the lines of the map
            for (int i = 0; i < height; i++)
            {
                mapArray.Add(sr.ReadLine());
            }
            // Reads in the scripts
            while (!sr.EndOfStream)
            {
                toWorld.AddScript(sr.ReadLine());
            }

            String[] map = mapArray.ToArray();
            
            int enemySpawnpoints = 0;
            // begin world init y
            for (int i = 0; i < map.Length; i++)
            {
                // begin world init x
                for (int j = 0; j < map[i].Length; j++)
                {
                    // begin char type switch
                    switch (map[i][j])
                    {
                            // Ocean
                        case 'B':
                            toWorld.PutGameObject(new NullGameObject(j, i));
                            toWorld.PutMapTile(new MapTile(j, i, ConsoleColor.DarkBlue));
                            break;
                            // Player spawnpoint
                        case 'P':
                            toWorld.PutGameObject(new NullGameObject(j, i));
                            toWorld.PutSpawnPoint(new SpawnPoint(j, i, "player"));
                            toWorld.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                            // Enemy spawnpoint
                        case 'E':
                            toWorld.PutGameObject(new NullGameObject(j, i));
                            toWorld.PutSpawnPoint(new SpawnPoint(j, i, "enemy" + enemySpawnpoints++));
                            toWorld.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                        case ' ':
                            toWorld.PutGameObject(new NullGameObject(j, i));
                            toWorld.PutMapTile(new MapTile(j, i, ConsoleColor.DarkYellow));
                            break;
                            // Wall
                        case '+':
                        case '|':
                        case '-':
                        default:
                            toWorld.PutGameObject(new Wall(j, i, map[i][j], ConsoleColor.Gray));
                            MapTile put = new MapTile(j, i);
                            put.background = ConsoleColor.Gray;
                            toWorld.PutMapTile(put);
                            break;

                    }
                    // end char type switch
                }
                // end world init x
            }
            // end world init y
        }
    }
}
